package com.kexuexiong.demo.bear.common.config;

import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.List;

@Component
@Slf4j
public class SentinelStartInit implements ApplicationRunner {


    private static final String remoteAddress = "localhost:8848";

    private static final String groupId = "Sentinel_config";

    private static final String flowDataId = "bear.flow.rule";

    private static final String degradeDataId = "bear.degrade.rule";

    private static final String systemDataId = "bear.system.rule";

    private static ConfigService configService;

    static {
        try {
            configService = NacosFactory.createConfigService(remoteAddress);
        } catch (NacosException e) {
            e.printStackTrace();
        }
    }


    @Override
    public void run(ApplicationArguments args) throws Exception {
        log.info("初始化sentinel在nacos中的配置数据...");
        loadFlowRules();
        loadDegradeRules();
        loadSystemRules();
    }

    private static void loadFlowRules() throws Exception {
        String content = getSentinelConfig("classpath:config/sentinel/FlowRule.json");
        configService.publishConfig(flowDataId, groupId, content);
        ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(remoteAddress, groupId, flowDataId,
                source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
                }));
        FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
    }

    private static void loadDegradeRules() throws Exception {
        String content = getSentinelConfig("classpath:config/sentinel/DegradeRule.json");
        configService.publishConfig(degradeDataId, groupId, content);
        ReadableDataSource<String, List<DegradeRule>> flowRuleDataSource = new NacosDataSource<>(remoteAddress, groupId, degradeDataId,
                source -> JSON.parseObject(source, new TypeReference<List<DegradeRule>>() {
                }));
        DegradeRuleManager.register2Property(flowRuleDataSource.getProperty());
    }

    private static void loadSystemRules() throws Exception {
        String content = getSentinelConfig("classpath:config/sentinel/SystemRule.json");
        configService.publishConfig(systemDataId, groupId, content);
        ReadableDataSource<String, List<SystemRule>> flowRuleDataSource = new NacosDataSource<>(remoteAddress, groupId, systemDataId,
                source -> JSON.parseObject(source, new TypeReference<List<SystemRule>>() {
                }));
        SystemRuleManager.register2Property(flowRuleDataSource.getProperty());
    }

    @NotNull
    private static String getSentinelConfig(String filePath) throws FileNotFoundException {
        File file = ResourceUtils.getFile(filePath);
        String content = "[]";
        if (!file.exists() || file.length() == 0) {
            return content;
        }
        try (FileInputStream fileInputStream = new FileInputStream(file)) {
            byte[] fileBuffer = new byte[(int) file.length()];
            fileInputStream.read(fileBuffer);
            content = new String(fileBuffer, "UTF-8");
        } catch (Exception e) {
            log.error("读取sentinel配置文件出错");
        }
        return content;
    }
}
